# -*- coding: utf-8 -*-
# keywords_heat.py
# Created by Hardy on 24th, Feb
# Copyright 2017 杭州网川教育科技有限公司. All rights reserved.

from querier.esquerier import ElasticSearchQuerier
from utils.province_code import PROVINCE_CODE

PROVINCE_DECODE = {v: k for k, v in PROVINCE_CODE.items()}


class WeiboUserPubStatMultiQuerier(ElasticSearchQuerier):
    def __init__(self, search_heat_querier):
        super(WeiboUserPubStatMultiQuerier, self).__init__(None, None, None)
        self.search_heat_querier = search_heat_querier

    def search(self, args):
        keywords = args.get('keywords')
        field = args.get('field')
        # keywords_set = args.get('keywords_set')
        filters = args.get('filters')
        res = []
        for w in keywords:
            a = {"word": w, "filters": filters, "field": field}
            res.append(self.search_heat_querier.search(a))
        return {'pub_stat': res}

    def _build_query(self, args): pass

    def _build_result(self, es_result, param): pass


class WeiboUserPubStatQuerier(ElasticSearchQuerier):
    def __init__(self, es, index, doc_type):
        super(WeiboUserPubStatQuerier, self).__init__(es, index, doc_type)

    def _build_query(self, args):
        word = args.get('word')
        field = args.get('field')
        filters = args.get('filters')
        if word:
            filters['keywords'] = word.split(';')

        query = self._gen_query(filters, field)
        print(query)
        return query, {}, {'keywords': filters['keywords'], 'field': field}

    @staticmethod
    def _build_result(es_result, param):
        agg = es_result['aggregations']
        field = param.get('field')
        data = extract_result(agg, field)
        return {
            "values": data['doc_counts'],
        }

    def _gen_query(self, filters, field):
        filter_clause = []

        if filters:
            filter_clause = self._add_filter_range_clause(filter_clause, filters, 'publish_timestamp')
            filter_clause = self._add_filter_clause(filter_clause, filters, 'source')
            for k in filters.get('keywords', []):
                filter_clause = self._add_filter_clause_search(filter_clause, [k])

        query = {
            "query": {
                "bool": {
                    "filter": filter_clause
                }
            },
            "aggs": {
                "user_hist": {
                    "terms": {
                        "field": field,
                        "size": 70
                    },
                    "aggs": {
                        "sum_likes": {"sum": {"field": "likes", "missing": 0}},
                    }
                }
            },
            "size": 0
        }

        return query

    @staticmethod
    def _add_filter_match(must_clause, filters, key):
        if key in filters:
            if filters[key]:
                clause = []
                must_clause.append({
                    'bool': {'should': clause}
                })
                values = filters[key]
                if isinstance(values, str):
                    values = values.split(' ')
                for fk in values:
                    clause.append({'match': {key: {'query': fk, 'minimum_should_match': '10<85% 20<10'}}})
        return must_clause

    @staticmethod
    def _add_filter_clause_search(filter_clause, keywords):
        clause = []
        filter_clause.append({
            'bool': {
                'should': clause,
                'minimum_should_match': 1
            }
        })
        for fk in keywords:
            clause.append({'term': {'keywords': fk}})
            clause.append({'match_phrase': {"weibo_text": {"query": fk}}})
        return filter_clause

    @staticmethod
    def _add_filter_clause(filter_clause, filters, key, cond='must'):
        if key in filters:
            if filters[key]:
                clause = []
                filter_clause.append({
                    'bool': {
                        cond: clause
                    }
                })
                for fk in filters[key]:
                    clause.append({'term': {key: fk}})
        return filter_clause

    @staticmethod
    def _add_filter_range_clause(filter_clause, filters, key):
        if key in filters:
            if filters[key]:
                clause = []
                filter_clause.append({
                    'bool': {
                        'must': clause
                    }
                })
                fk = filters[key]
                if not isinstance(fk, list) or len(fk) < 1:
                    pass
                else:
                    min_fk = fk[0]
                    if len(fk) >= 2:
                        max_fk = fk[1]
                    else:
                        max_fk = None
                    if min_fk is not None and min_fk != 'null':
                        clause.append({'range': {key: {"gte": min_fk}}})
                    if max_fk is not None and max_fk != 'null':
                        clause.append({'range': {key: {"lte": max_fk}}})
        return filter_clause


def extract_result(agg, field):
    buckets = agg['user_hist']['buckets']

    doc_counts = dict()
    sum_likes = dict()
    if field == 'province':
        for b in buckets:
            k = province_decode(b['key'])
            doc_counts[k] = b['doc_count']
            sum_likes[k] = b['sum_likes']['value']
    else:
        for b in buckets:
            k = province_decode(b['key'])
            doc_counts[k] = b['doc_count']
            sum_likes[k] = b['sum_likes']['value']

    sorted_keys = sorted(doc_counts.keys())
    return {
        'doc_counts': [{'key': k, 'value': doc_counts[k]} for k in sorted_keys],
        'sum_likes': [{'key': k, 'value': sum_likes[k]} for k in sorted_keys],
    }


def province_decode(province_code):
    return PROVINCE_DECODE.get(province_code, '未知')
